﻿using System;
using UnityEngine.UI;
using UnityEngine;
using shaco.ActionExtensions;
using ShootMan;
using System.Collections;

[shaco.UILayerIndex((int)ShootMan.GlobalDefines.UILayers.Game)]
[shaco.UILayerOpenAsync]
public class GameLayer : UnityEngine.MonoBehaviour
{
    public Button buttonResetScore;
    public Button buttonAddGravity;
    public Button buttonReduceGravity;

    public Text textGravity;
    public Text textScore;

    [NonSerialized]
    public int totalShootCount;
    [NonSerialized]
    public bool isGameOver = false;

    ShootMan.GameRoot _gameRoot = null;
    IEnumerator _coroutineGameProcess;
    shaco.Base.ISubject<Vector3> _subjectGravity = new shaco.Base.Subject<Vector3>();

    void OnUIOpen(ShootMan.GameRoot.GameLayerOpenArg arg)
    {
        UnloadUnusedAssets();

        _gameRoot = arg.root;

        //开始游戏逻辑树
        this.StartCoroutine(_coroutineGameProcess = new GameProcessSpawnEnemy().Process(_gameRoot));

        //自定义观察数据发生变化的处理方式
        //如果不调用该方法则使用内置的实例化数据处理
        _subjectGravity.LookAt(() => UnityEngine.Physics.gravity, value => UnityEngine.Physics.gravity = value);

        //观察重力发生变化数据，并设置ui文本显示
        _subjectGravity.OnValueUpdate(value => this.textGravity.text = value.ToString()).Start(this);

        //分数发生变化，并设置ui文本显示
        this.AddAutoReleaseEvent<ShootMan.ShootAddScoreEvent>((sender, arg) =>
        {
            var valueString = _gameRoot.currentScore.ToString();
            if (valueString != this.textScore.text)
            {
                this.textScore.StopAllAction(true);
                if (!this.isGameOver)
                    this.textScore.ScaleTo(new Vector3(2.0f, 2.0f, 2.0f), 0.1f).Pingpong().Repeat(2);
            }
            this.textScore.text = valueString;
        });

        //点击按钮增加重力
        this.buttonAddGravity.onClick.AddListener(this.OnClickAddGravity);

        // 点击按钮减少重力
        this.buttonReduceGravity.onClick.AddListener(this.OnClickReduceGravity);

        // 点击重置分数
        this.buttonResetScore.onClick.AddListener(this.OnClickResetScore);

        //游戏结束
        this.AddAutoReleaseEvent<ShootMan.GameOverEvent>((sender, arg) =>
        {
            OnClickForceGameEnd();

            //记录游戏射击次数
            this.totalShootCount = arg.totalShootCount;
        });

        //读取数据
        _subjectGravity.value = shaco.GameHelper.datasave.ReadVector3("gravity", UnityEngine.Physics.gravity);
        _gameRoot.currentScore = shaco.GameHelper.datasave.ReadInt("score", 0);

        //打开网络数据处理界面
        shaco.GameHelper.ui.OpenUI<GameNetLayer>();
    }

    void OnUIClose()
    {
        //保存数据
        shaco.GameHelper.datasave.WriteVector3("gravity", _subjectGravity.value);
        shaco.GameHelper.datasave.WriteInt("score", _gameRoot.currentScore);

        //注销事件
        this.buttonAddGravity.onClick.RemoveListener(this.OnClickAddGravity);
        this.buttonReduceGravity.onClick.RemoveListener(this.OnClickReduceGravity);
        this.buttonResetScore.onClick.RemoveListener(this.OnClickResetScore);
    }

    public ShootMan.GameRoot GetGameRoot()
    {
        return _gameRoot;
    }

    void OnClickResetScore()
    {
        _gameRoot.currentScore = 0;
        this.textScore.text = "0";

        if (shaco.GameHelper.datasave.ContainsKey("score"))
            shaco.GameHelper.datasave.Remove("score");
    }

    void OnClickAddGravity()
    {
        _subjectGravity.value = _subjectGravity.value - new Vector3(0, 1, 0);
    }

    void OnClickReduceGravity()
    {
        _subjectGravity.value = _subjectGravity.value + new Vector3(0, 1, 0);
    }

    public void OnClickForceGameEnd()
    {
        //记录游戏结束状态，以便禁止玩家再次移动和射击
        this.isGameOver = true;

        //停止游戏逻辑
        if (null != _coroutineGameProcess)
        {
            StopCoroutine(_coroutineGameProcess);
            _coroutineGameProcess = null;
        }

        //停止所有物体下落
        var allEnemies = GameObject.FindObjectsOfType<ShootMan.DefaultEnemyController>();

        for (int i = 0; i < allEnemies.Length; ++i)
        {
            var controller = allEnemies[i];
            var rigidbody = controller.gameObject.GetComponent<UnityEngine.Rigidbody>();
            rigidbody.constraints = UnityEngine.RigidbodyConstraints.FreezeAll;
        }

        //卸载游戏资源
        this.UnloadAllAssets();

        shaco.Log.Info("open endlayer", UnityEngine.Color.white);
        shaco.GameHelper.ui.CloseUI<GameNetLayer>();
        shaco.GameHelper.ui.OpenUI<EndLayer>();
    }

    //游戏结束时候销毁缓存池资源
    void UnloadAllAssets()
    {
        shaco.Log.Info("GameLayer UnloadAllAssets: will release all game data");

        //部分内存池资源精准卸载
        var tabelObjectPoolKeys = new string[]{typeof(ShootMan.DefaultBulletController).ToTypeString(),
                                               typeof(ShootMan.SyncTransformPositionNetEvent).ToTypeString(),
                                               typeof(ShootMan.SyncShootBulletNetEvent).ToTypeString(),
                                               typeof(ShootMan.NetEvent.C2S_NotifySelfPosition).ToTypeString(),
                                               typeof(ShootMan.NetEvent.C2S_NotifySelfShoot).ToTypeString()
                                              };

        foreach (var iter in tabelObjectPoolKeys)
        {
            if (shaco.GameHelper.objectpool.IsInPool(iter))
                shaco.GameHelper.objectpool.DestroyAllObjects(iter);
        }

        ShootMan.cfg_spawn_enemy.Foreach((key, value) =>
        {
            if (shaco.GameHelper.objectpool.IsInPool(value.PREFAB_NAME))
                shaco.GameHelper.objectpool.DestroyAllObjects(value.PREFAB_NAME);
            return true;
        });

        //这里检查关闭所有动画，否则可能界面销毁了动画还在播放
        this.textScore.StopAllAction(true);
        UnloadUnusedAssets();
    }

    static public void UnloadUnusedAssets()
    {
        shaco.GameHelper.res.SetCurrentPackageName("DefaultPackage");
        shaco.GameHelper.res.UnloadUnusedAssetsAsync();

        shaco.GameHelper.res.SetCurrentPackageName("scripts");
        shaco.GameHelper.res.UnloadUnusedAssetsAsync();

        shaco.GameHelper.res.SetCurrentPackageName("configs");
        shaco.GameHelper.res.UnloadUnusedAssetsAsync();

        shaco.GameHelper.res.SetCurrentPackageName("audio");
        shaco.GameHelper.res.UnloadUnusedAssetsAsync();

        shaco.GameHelper.res.SetCurrentPackageName("DefaultPackage");
    }
}